package craky.keeper;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Action;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import craky.component.JImagePane;
import craky.componentc.JCButton;
import craky.componentc.JCLabel;
import craky.componentc.JCPopupMenu;
import craky.componentc.JCSlider;
import craky.layout.LineLayout;

public class ColorChooserPopup extends JCPopupMenu implements ActionListener,
		ChangeListener {
	private static final long serialVersionUID = -8966381243406755861L;
	private static final Font LABEL_FONT = new Font("Tahoma", 0, 12);
	private JCSlider sliderR;
	private JCSlider sliderG;
	private JCSlider sliderB;
	private JCLabel lbR;
	private JCLabel lbG;
	private JCLabel lbB;
	private JCLabel lbPurview;
	private JCButton btnOk;
	private JCButton btnCancel;
	private Color oldColor;
	private Color currentColor;
	private int r;
	private int g;
	private int b;
	private boolean canceled;
	private Action changedAction;

	public ColorChooserPopup() {
		this(new Color(0, 0, 0), null);
	}

	public ColorChooserPopup(Color color, Action changedAction) {
		this.changedAction = changedAction;
		setColor(color == null ? new Color(0, 0, 0) : color, false);
		initUI();
	}

	private void initUI() {
		setOpaque(false);
		setFocusable(false);
		setLayout(new BorderLayout());
		setPreferredSize(new Dimension(236, 123));
		initChildren();
	}

	private void initChildren() {
		JImagePane mainPane = new JImagePane();
		EmptyComponent ecR = new EmptyComponent();
		EmptyComponent ecG = new EmptyComponent();
		EmptyComponent ecB = new EmptyComponent();
		EmptyComponent ecButton = new EmptyComponent();
		EmptyComponent ecPurviewAndButton = new EmptyComponent();
		JCLabel lbRT = new JCLabel("R: ");
		JCLabel lbGT = new JCLabel("G: ");
		JCLabel lbBT = new JCLabel("B: ");
		this.sliderR = new JCSlider(0, 255, this.r);
		this.sliderG = new JCSlider(0, 255, this.g);
		this.sliderB = new JCSlider(0, 255, this.b);
		this.lbR = new JCLabel(this.r + "");
		this.lbG = new JCLabel(this.g + "");
		this.lbB = new JCLabel(this.b + "");
		this.lbPurview = new JCLabel();
		this.btnOk = new JCButton("确定");
		this.btnCancel = new JCButton("取消");

		mainPane.setBackground(new Color(234, 238, 240));
		mainPane.setLayout(new LineLayout(0, 11, 10, 1));
		ecR.setLayout(new LineLayout(0, 5, 5, 5, 0, 10, 10, 0));
		ecG.setLayout(new LineLayout(0, 5, 5, 5, 0, 10, 10, 0));
		ecB.setLayout(new LineLayout(0, 5, 5, 5, 0, 10, 10, 0));
		ecButton.setLayout(new LineLayout(3, 0, 0, 0, 0, 10, 10, 0));
		ecPurviewAndButton.setLayout(new LineLayout(5, 6, 5, 5, 5, 10, 11, 0));
		ecR.setPreferredSize(new Dimension(-1, 25));
		ecG.setPreferredSize(ecR.getPreferredSize());
		ecB.setPreferredSize(ecR.getPreferredSize());
		ecPurviewAndButton.setPreferredSize(new Dimension(-1, 35));
		this.lbR.setPreferredSize(new Dimension(22, -1));
		this.lbG.setPreferredSize(this.lbR.getPreferredSize());
		this.lbB.setPreferredSize(this.lbR.getPreferredSize());
		lbRT.setFont(LABEL_FONT);
		lbGT.setFont(LABEL_FONT);
		lbBT.setFont(LABEL_FONT);
		this.lbR.setFont(LABEL_FONT);
		this.lbG.setFont(LABEL_FONT);
		this.lbB.setFont(LABEL_FONT);
		this.lbPurview.setBorder(new LineBorder(Color.BLACK));
		this.lbPurview.setBackgroundAlpha(1.0F);
		this.btnOk.setFocusable(false);
		this.btnOk.setPreferredSize(new Dimension(50, 20));
		this.btnCancel.setPreferredSize(this.btnOk.getPreferredSize());
		this.btnCancel.setFocusable(false);
		this.sliderR.addChangeListener(this);
		this.sliderG.addChangeListener(this);
		this.sliderB.addChangeListener(this);
		this.btnOk.addActionListener(this);
		this.btnCancel.addActionListener(this);

		ecR.add(lbRT, "StartFill");
		ecR.add(this.sliderR, "MiddleFill");
		ecR.add(this.lbR, "EedFill");
		ecG.add(lbGT, "StartFill");
		ecG.add(this.sliderG, "MiddleFill");
		ecG.add(this.lbG, "EedFill");
		ecB.add(lbBT, "StartFill");
		ecB.add(this.sliderB, "MiddleFill");
		ecB.add(this.lbB, "EedFill");
		ecPurviewAndButton.add(this.lbPurview, "MiddleFill");
		ecPurviewAndButton.add(ecButton, "End");
		ecButton.add(this.btnOk, "EedFill");
		ecButton.add(this.btnCancel, "EedFill");
		mainPane.add(ecR, "StartFill");
		mainPane.add(ecG, "StartFill");
		mainPane.add(ecB, "StartFill");
		mainPane.add(ecPurviewAndButton, "EedFill");
		add(mainPane, "Center");
	}

	private void resetSlider() {
		this.sliderR.setValue(this.r);
		this.sliderG.setValue(this.g);
		this.sliderB.setValue(this.b);
	}

	private void resetLabel() {
		this.lbR.setText(this.r + "");
		this.lbG.setText(this.g + "");
		this.lbB.setText(this.b + "");
		this.lbPurview.setBackground(this.currentColor);
	}

	public void setColor(Color color, boolean display) {
		this.oldColor = (this.currentColor = color);
		this.r = color.getRed();
		this.g = color.getGreen();
		this.b = color.getBlue();
		this.canceled = true;

		if (display) {
			resetSlider();
			resetLabel();
		}
	}

	public Color getColor() {
		return this.canceled ? this.oldColor : this.currentColor;
	}

	public Color getCurrentColor() {
		return this.currentColor;
	}

	public boolean isCanceled() {
		return this.canceled;
	}

	@Override
	public void setVisible(boolean visible) {
		if (visible) {
			setColor(this.oldColor, true);
		}

		super.setVisible(visible);
	}

	public void actionPerformed(ActionEvent e) {
		this.canceled = (e.getSource() != this.btnOk);
		setVisible(false);
	}

	public void stateChanged(ChangeEvent e) {
		Object source = e.getSource();

		if (source == this.sliderR) {
			this.r = this.sliderR.getValue();
		} else if (source == this.sliderG) {
			this.g = this.sliderG.getValue();
		} else if (source == this.sliderB) {
			this.b = this.sliderB.getValue();
		}

		this.currentColor = new Color(this.r, this.g, this.b);
		resetLabel();

		if (this.changedAction != null) {
			this.changedAction.actionPerformed(new ActionEvent(this, 0, null));
		}
	}
}